#
# This file is a part of the open-eBackup project.
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at
# http://mozilla.org/MPL/2.0/.
#
# Copyright (c) [2024] Huawei Technologies Co.,Ltd.
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#

from abc import ABC, abstractmethod

from common.common import check_path_legal
from common.const import RepositoryDataTypeEnum
from generaldb.gbase8a.common.const import JsonConstant, GbasePath
from generaldb.gbase8a.common.gbase_common import get_local_uuid
from generaldb.gbase8a.job_manager import JobManager


class BaseParam(ABC):
    # 该类定义为抽象基类，不能直接实例化
    def __init__(self, json_param, job_manager: JobManager, log_obj):
        self._json_param = json_param
        self._log_obj = log_obj
        self._pid = job_manager.pid
        self._job_id = job_manager.job_id
        self._sub_job_id = job_manager.sub_job_id
        self._log_obj.info("Start to get param file.")
        if not self._json_param:
            raise Exception(f"json param is null.")

    def get_log_common(self):
        key_list = ["pid", "jobId", "subjobId"]
        value_list = [self._pid, self._job_id, self._sub_job_id]
        k_v_tuples = zip(key_list, value_list)
        return " ".join([f"{k}:{v}" for k, v in k_v_tuples if v])

    def get_copy(self):
        """
        获取job -> copy
        :return: list
        """
        return self._json_param.get(JsonConstant.JOB, {}).get(JsonConstant.COPY, [])

    def get_copy_key(self, copy_index: int, key: str):
        """
        获取指定索引的副本信息中的指定字段 job -> copy[copy_index] -> key
        :param copy_index: 副本索引
        :param key: 待获取的字段名称
        """
        if not self._json_param:
            self._log_obj.error(f"Json param is null. {self.get_log_common()}")
            return ""
        copy = self._json_param.get(JsonConstant.JOB, {}).get(JsonConstant.COPY, [])
        if not copy:
            self._log_obj.error(f"Copy is null. {self.get_log_common()}")
            return ""
        error_negative_index = (copy_index < 0 and len(copy) < -copy_index)
        error_positive_index = (copy_index > 0 and len(copy) < copy_index + 1)
        if error_negative_index or error_positive_index:
            self._log_obj.error(f"The copy_index is out of range. number of copies:{len(copy)}")
            return ''
        value = copy[copy_index].get(key)
        if not value:
            self._log_obj.error(f"Get value id failed. {self.get_log_common()}")
        return value

    def get_copy_id(self, copy_index: int = -1):
        """
        获取 获取指定索引的副本信息中的id字段 job -> copy[copy_index] -> id
        :param copy_index: 副本索引默认取-1
        :return: str
        """
        return self.get_copy_key(copy_index, JsonConstant.ID)

    def get_job_extendinfo(self):
        """
        获取job下的extendInfo，job -> extendInfo
        :return: dict
        """
        return self._json_param.get(JsonConstant.JOB, {}).get(JsonConstant.EXTEND_INFO, {})

    def get_job_jobid(self):
        """
        获取job下jobId，job -> jobId
        :return: str
        """
        return self._json_param.get(JsonConstant.JOB, {}).get(JsonConstant.JOB_ID, {})

    def get_job_jobparam(self):
        """
        获取job下jobParam，job -> jobParam
        :return: dict
        """
        return self._json_param.get(JsonConstant.JOB, {}).get(JsonConstant.JOB_PARAM, {})

    def get_job_jobparam_backuptype(self):
        """
        获取 job -> jobParam -> backupType
        :return: int
        """
        return self._json_param.get(JsonConstant.JOB, {}).get(JsonConstant.JOB_PARAM, {}).get(JsonConstant.BACKUP_TYPE,
                                                                                              -1)

    def get_job_protectenv(self):
        """
         获取 job -> protectEnv
        :return: dict
        """
        return self._json_param.get(JsonConstant.JOB, {}).get(JsonConstant.PROTECT_ENV, {})

    def get_job_protectenv_id(self):
        """
         获取资源id job -> protectEnv -> id
        :return: str
        """
        return self._json_param.get(JsonConstant.JOB, {}).get(JsonConstant.PROTECT_ENV, {}).get(JsonConstant.ID, '')

    def get_job_protectenv_nodes(self):
        """
        获取 job -> protectEnv -> nodes
        :return:
        """
        return self._json_param.get(JsonConstant.JOB, {}).get(JsonConstant.PROTECT_ENV, {}).get(JsonConstant.NODES, [])

    def get_local_job_protectenv_nodes(self):
        """
         通过判断id，筛选存在于当前主机上的node信息
        :return: list
        """
        host_sn = get_local_uuid()
        result_list = []
        if not host_sn:
            return []
        nodes = self.get_job_protectenv_nodes()
        if not nodes:
            return []
        for node in nodes:
            id_info = node.get(JsonConstant.ID, '')
            if not id_info:
                return []
            if id_info == host_sn:
                result_list.append(node)
        return result_list

    def get_job_protectobject(self):
        """
        获取 job -> protectObject
        :return: dict
        """
        return self._json_param.get(JsonConstant.JOB, {}).get(JsonConstant.PROTECT_OBJECT, {})

    def get_job_protectobject_extendinfo(self):
        """
        获取 job -> protectObject -> extendInfo
        :return:
        """
        return self._json_param.get(JsonConstant.JOB, {}).get(JsonConstant.PROTECT_OBJECT, {}).get(
            JsonConstant.EXTEND_INFO, {})

    def get_job_protectobject_extendinfo_key(self, key):
        """
        获取 job -> protectObject -> extendInfo -> key
        :return:
        """
        extend_info = self.get_job_protectobject_extendinfo()
        value = extend_info.get(key)
        # 这里只判断key不存在的情况
        if value is None:
            return False, ''
        return True, value

    @abstractmethod
    def get_job_repositories(self):
        # 抽象方法子类必须实现
        pass

    def get_designated_path_ex(self, rep_type, repositories: list):
        if not repositories:
            self._log_obj.error(f"Repositories is null. rep_type:{rep_type} {self.get_log_common()}")
            return ""
        for repository in repositories:
            if repository.get(JsonConstant.REPOSITORY_TYPE, "") != rep_type:
                continue
            path_array = repository.get(JsonConstant.PATH, [])
            if len(path_array) <= 0 or not path_array[0]:
                continue
            # 返回取到得路径中的第一个符合合法性校验的
            for path in path_array:
                if check_path_legal(path, GbasePath.GBASE_FILESYSTEM_MOUNT_PATH):
                    return path
        self._log_obj.error(f"Get path error. rep_type:{rep_type} {self.get_log_common()}")
        return ""

    def get_designated_path(self, rep_type):
        repositories = self.get_job_repositories()
        return self.get_designated_path_ex(rep_type, repositories)

    def get_cache_path(self):
        return self.get_designated_path(RepositoryDataTypeEnum.CACHE_REPOSITORY.value)

    def get_data_path(self):
        return self.get_designated_path(RepositoryDataTypeEnum.DATA_REPOSITORY.value)

    def get_meta_path(self):
        return self.get_designated_path(RepositoryDataTypeEnum.META_REPOSITORY.value)

    def get_self_define_param(self):
        """
        获取自定义参数， job -> protectEnv -> extendInfo -> customParams
        :return: str
        """
        ret, custom_params = self.get_job_protectobject_extendinfo_key(JsonConstant.CUSTOM_PARAMS)
        if not ret:
            return ''
        return custom_params

    def parse_custom_str_to_dict(self) -> dict:
        """
        转换自定义参数为字典
        """
        custom_str = self.get_self_define_param()
        custom_list = [kv_str.split("=", 1) for kv_str in custom_str.split(",")]
        custom_dict = {kv_list[0]: kv_list[1] for kv_list in custom_list if len(kv_list) == 2}
        return custom_dict

    def get_specified_self_define_params(self, param_name):
        """
        获取指定名称的自定义参数
        :param param_name:自定义参数名称
        :return: str
        """
        custom_dict = self.parse_custom_str_to_dict()
        if not custom_dict:
            return []
        return custom_dict.get(param_name, '')

    def get_subjob(self):
        """
        获取 subJob
        :return: dict
        """
        return self._json_param.get(JsonConstant.SUB_JOB, {})

    def get_subjob_key(self, key: str):
        """
        获取 subJob -> key
        :return: str
        """
        value = self._json_param.get(JsonConstant.SUB_JOB, {}).get(key)
        return value

    def get_subjob_jobid(self):
        """
        获取 subJob -> jobId
        :return:str
        """
        return self.get_subjob_key(JsonConstant.JOB_ID)

    def get_subjob_jobinfo(self):
        """
        获取 subJob -> jobInfo
        :return:str
        """
        return self.get_subjob_key(JsonConstant.JOB_INFO)

    def get_subjob_jobname(self):
        """
        获取 subJob -> jobName
        :return:str
        """
        return self.get_subjob_key(JsonConstant.JOB_NAME)

    def get_subjob_jobpriority(self):
        """
        获取 subJob -> jobPriority
        :return:str
        """
        return self.get_subjob_key(JsonConstant.JOB_PRIORITY)

    def get_subjob_jobtype(self):
        """
        获取 subJob -> jobType
        :return:str
        """
        return self.get_subjob_key(JsonConstant.JOB_TYPE)

    def get_subjob_policy(self):
        """
        获取 subJob -> policy
        :return:str
        """
        return self.get_subjob_key(JsonConstant.POLICY)

    def get_subjob_subjobid(self):
        """
        获取 subJob -> subJobId
        :return:str
        """
        return self.get_subjob_key(JsonConstant.SUB_JOB_ID)
